(module data-structures (lib "eopl.ss" "eopl")
  
  (require "lang.scm")                  ; for expression?
  (require "store.scm")  ;; for Explicit refs   
  (provide (all-defined))               ; too many things to list
  
  ;;;;;;;;;;;;;;;; expressed values ;;;;;;;;;;;;;;;;
  
  ;;; an expressed value is either a number, a boolean or a procval.
  
  (define-datatype expval expval?
    (num-val
     (value number?))
    (bool-val
     (boolean boolean?))
    (proc-val 
     (proc proc?))
    (ref-val
     (ref reference?))    
    )
  
  ;;; extractors:
  
  (define expval->num
    (lambda (v)
      (cases expval v
	(num-val (num) num)
	(else (expval-extractor-error 'num v)))))
  
  (define expval->bool
    (lambda (v)
      (cases expval v
	(bool-val (bool) bool)
	(else (expval-extractor-error 'bool v)))))
  
  (define expval->proc
    (lambda (v)
      (cases expval v
	(proc-val (proc) proc)
	(else (expval-extractor-error 'proc v)))))

   (define expval->ref
    (lambda (v)
      (cases expval v
	(ref-val (ref) ref)
	(else (expval-extractor-error 'reference v)))))  
  
  (define expval-extractor-error
    (lambda (variant value)
      (eopl:error 'expval-extractors "Looking for a ~s, found ~s"
                  variant value)))
  
  ;;;;;;;;;;;;;;;; procedures ;;;;;;;;;;;;;;;;
  
  (define-datatype proc proc?
    (procedure
     (bvar symbol?)
     (body expression?)
     (env environment?)))
  
  (define-datatype environment environment?
    (empty-env)
    (extend-env 
     (bvar symbol?)
     (bval expval?)
     (saved-env environment?))
    (extend-env-recursively
     (id symbol?)
     (bvar symbol?)
     (body expression?)
     (saved-env environment?)))
  
  )